home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 June: Reference Library / Dev.CD Jun 96 RL / Dev.CD Jun 96 RL.toast / Technical Documentation / develop / develop Issue 24 / develop Issue 24 code / Scriptable Database 1.0a15 / Application / DBElementToken.cp < prev    next >
Encoding:
Text File  |  1996-02-19  |  22.9 KB  |  693 lines  |  [TEXT/CWIE]

  1.  
  2. #include "DBElementToken.h"
  3. #include "DBElementTokenIterator.h"
  4.  
  5. #include "Application.h"
  6. #include "DBElement.h"
  7. #include "DBProperty.h"
  8. #include "Transaction.h"
  9. #include "ScriptableDBDocument.h"
  10. #include "AbstractProperty.h"
  11.  
  12. #include <AERegistry.h>
  13. #include <ASRegistry.h>
  14.  
  15. #include "Exceptions.h"
  16.  
  17. TDescriptor GetDataAsDescriptor(TTransaction* t, AConst<TDBProperty> propertyRecord);
  18.  
  19.  
  20. //--------------------------------------------------------------------------------
  21. // GetDataAsDescriptor
  22. //--------------------------------------------------------------------------------
  23. TDescriptor GetDataAsDescriptor(TTransaction* t, AConst<TDBProperty> propertyRecord)
  24. {
  25.     TDescriptor result;
  26.     
  27.     if(propertyRecord.Exists())
  28.     {
  29.         propertyRecord->GetTypedData(t, TDescriptorDataReference(result));
  30.     }
  31.     
  32.     return result;
  33. } // GetDataAsDescriptor
  34.  
  35. #define clDBElementToken 33
  36.  
  37. #pragma segment ObjectResident
  38. ImplementSmallClassData(TDBElementToken, clDBElementToken);
  39.  
  40. //--------------------------------------------------------------------------------
  41. // TDBElementToken::TDBElementToken
  42. //--------------------------------------------------------------------------------
  43. TDBElementToken::TDBElementToken(AConst<TDBElement> record) : fRecord(record)
  44.     {
  45.     record->AddReference();
  46.     }
  47.  
  48. //--------------------------------------------------------------------------------
  49. // TDBElementToken::~TDBElementToken
  50. //--------------------------------------------------------------------------------
  51. TDBElementToken::~TDBElementToken()
  52.     {
  53.     fRecord->RemoveReference();
  54.     }
  55.     
  56. //--------------------------------------------------------------------------------
  57. // TDBElementToken::CloneOwnedObjects
  58. //--------------------------------------------------------------------------------
  59. void TDBElementToken::CloneOwnedObjects()
  60.     {
  61.     //
  62.     // fRecord has been cloned, so we need to add one more reference to it
  63.     //    
  64.     fRecord->AddReference();
  65.     } // TDBElementToken::CloneOwnedObjects
  66.  
  67. //--------------------------------------------------------------------------------
  68. // TDBElementToken::ObjectClass
  69. //--------------------------------------------------------------------------------
  70. DescType TDBElementToken::ObjectClass(const TAETransaction& t, Boolean /*recordedClass*/)
  71. {
  72.     DescType objectClass = cObject;
  73.     long unusedLength = 0;
  74.     long unusedType = 0;
  75.     AConst<TDBProperty> propertyRecord = fRecord->GetPropertyRecord(TTransactionSuite::GetTransactionFromEvent(t), pClass);
  76.     
  77.     if(propertyRecord.Exists())
  78.         propertyRecord->GetTypedData(TTransactionSuite::GetTransactionFromEvent(t), TUpdataDataReference(typeType, (char*)&objectClass, sizeof(DescType), sizeof(DescType)));
  79.     
  80.     return objectClass;
  81. }
  82.  
  83. //--------------------------------------------------------------------------------
  84. // TDBElementToken::DerivedFromOSLClass
  85. //--------------------------------------------------------------------------------
  86. Boolean TDBElementToken::DerivedFromOSLClass(const TAETransaction& t, DescType objectClass)
  87. {
  88.     return ((objectClass == this->ObjectClass(t)) || (Inherited::DerivedFromOSLClass(t, objectClass)));
  89. }
  90.  
  91. //--------------------------------------------------------------------------------
  92. // TDBElementToken::ParentObject
  93. //--------------------------------------------------------------------------------
  94. TAbstractScriptableObject* TDBElementToken::ParentObject(const TAETransaction& t)
  95. {
  96.     TAbstractScriptableObject* parent = nil;
  97.     AConst<TDBRecord> parentElement = fRecord->TreeOwner(TTransactionSuite::GetTransactionFromEvent(t));
  98.  
  99.     //
  100.     // If this node has a parent, then it is not the metaroot
  101.     //
  102.     if(parentElement.Exists())
  103.     {
  104.         parent = new TDBElementToken(parentElement->DBElementCursor());
  105.     }
  106.     //
  107.     // The parent of the metaroot is the scriptable db document
  108.     // that contains this database document.
  109.     //
  110.     else
  111.     {
  112.         TDatabaseDocument* doc = fRecord->DBDocument();
  113.         parent = TApplication::Instance()->FindDocument(doc->ObjectsKeySpace());
  114.     }
  115.     
  116.     return parent;
  117. }
  118.  
  119. //--------------------------------------------------------------------------------
  120. // TDBElementToken::ElementIterator
  121. //--------------------------------------------------------------------------------
  122. TAbstractObjectIterator* TDBElementToken::ElementIterator(const TAETransaction& t)
  123. {    
  124.     // AConst<TDBRecord> elements = fRecord->Elements()->DBRecordCursor();
  125.     AConst<TDBElement> elements = fRecord->Elements(TTransactionSuite::GetTransactionFromEvent(t));
  126.  
  127.     TAbstractObjectIterator* iter = nil;
  128.     
  129.     if(elements.Exists())
  130.         {
  131.         iter = new TDBElementTokenIterator(t, elements->DBRecordCursor());
  132.         }
  133.         
  134.     return iter;
  135. }
  136.  
  137.  
  138. //--------------------------------------------------------------------------------
  139. // TDBElementToken::AccessByProperty
  140. //--------------------------------------------------------------------------------
  141. TAbstractScriptableObject* TDBElementToken::AccessByProperty(const TAETransaction& t, DescType propertyIdentifier)
  142. {
  143.     TAbstractScriptableObject* result = nil;
  144.     
  145.     //
  146.     // If we can generate a description for this property,
  147.     // then call Inherited:: to make the property token
  148.     //
  149.     if(this->DescriptionOfProperty(t, propertyIdentifier) != nil)
  150.     {
  151.         result = Inherited::AccessByProperty(t, propertyIdentifier);
  152.     }
  153.     else
  154.     {
  155.         //
  156.         // Problem:  For this database, there should be some way
  157.         // to create a property that does not exist yet under some
  158.         // situations (maybe some databases will allow any property
  159.         // to be added to any element, but most databases will
  160.         // probably restrict the properties that each element can
  161.         // have).
  162.         //
  163.         // We also need to specify that some properties are read
  164.         // only (maybe?)
  165.         //
  166. #if 0
  167.         AConst<TDBProperty> propertyRecord = fRecord->GetPropertyRecord(propertyIdentifier);
  168.         if(propertyRecord.Exists())
  169. #endif
  170.         {
  171.             //
  172.             // We need some way to determine what the default type
  173.             // and best type for any given property should be.
  174.             //
  175.             result = new TGenericProperty;
  176.             ((TGenericProperty*)result)->IGenericProperty(this, TPropertyDataDescription(propertyIdentifier, 0, typeWildCard, typeWildCard));
  177.         }
  178.     }
  179.     
  180.     return result;
  181. }
  182.  
  183.  
  184. //================================================================================
  185. // Class TDescriptorComparisonObject
  186. //================================================================================
  187. class TDescriptorComparisonObject : public TAbstractDBComparisonObject
  188. {
  189. private:
  190.     const TDescriptor                fSearchKey;
  191.     
  192. public:
  193.                                     TDescriptorComparisonObject(TDescriptor& searchKey) : fSearchKey(searchKey) {};
  194.  
  195.     virtual CompareEnumeration        TestObject(TTransaction*, AConst<TDBRecord>);
  196. };
  197.  
  198. //--------------------------------------------------------------------------------
  199. // TDescriptorComparisonObject::TestObject
  200. //--------------------------------------------------------------------------------
  201. CompareEnumeration TDescriptorComparisonObject::TestObject(TTransaction* t, AConst<TDBRecord> testObject)
  202. {
  203.     //
  204.     // This is not a very fast way to compare, but it will do for now.
  205.     //
  206.     TDescriptor testName = GetDataAsDescriptor(t, testObject->DBElementCursor()->GetPropertyRecord(t, pName));
  207.  
  208.     //
  209.     // This AppleEvent API that removes information from the result is annoying,
  210.     // because it forces us to compare twice (ick).
  211.     //
  212.     // kAEGreaterThan
  213.     // kAELessThan
  214.     //
  215.     Boolean isLess = fSearchKey.Compare(kAELessThan, testName);
  216.     Boolean isGreater = fSearchKey.Compare(kAEGreaterThan, testName);
  217.     
  218.     //
  219.     // kSecondObjectComesBefore = -1,
  220.     // kObjectKeysEqual = 0,
  221.     // kSecondObjectComesAfter = 1
  222.     //
  223.     return (isGreater ? kSecondObjectComesAfter : (isLess ? kSecondObjectComesBefore : kObjectKeysEqual));
  224. } // TDescriptorComparisonObject::TestObject
  225.  
  226. //--------------------------------------------------------------------------------
  227. // TDBElementToken::AccessByUniqueID
  228. //--------------------------------------------------------------------------------
  229. TAbstractScriptableObject* TDBElementToken::AccessByUniqueID(const TAETransaction& t, DescType desiredClass, TDescriptor uniqueID)
  230. {
  231.     TAbstractScriptableObject* result = nil;
  232.     long theRecordIndex = uniqueID.GetSInt32Data();
  233.     
  234.     //
  235.     // Get the specified record from the database.  The record
  236.     // _must_ be a database element (not a property); if this is
  237.     // a token for the metaroot, then allow any record in any tree
  238.     // to be returned.  Otherwise, require that the record we found
  239.     // be a child of this record.
  240.     //    
  241.     AConst<TDBElement> theRecord = fRecord->DBDocument()->GetRecordCursor(theRecordIndex)->DBElementCursor();
  242.     if(theRecord.Exists())
  243.     {
  244.         AConst<TDBRecord> theRecordOwner = theRecord->TreeOwner(TTransactionSuite::GetTransactionFromEvent(t));
  245.         if(this->IsMetaRoot() || (theRecordOwner->RecordIndex() == fRecord->RecordIndex()))
  246.         {
  247.             result = new TDBElementToken(theRecord);
  248.             if(result->DerivedFromOSLClass(t, desiredClass) == false)
  249.             {
  250.                 result->DisposeDesignator();
  251.                 result = nil;
  252.             }
  253.         }
  254.     }
  255.     
  256.     //
  257.     // If we could not find an appropriate record with the given ID,
  258.     // then call Inherited.
  259.     //
  260.     if(result == nil)
  261.         result = Inherited::AccessByUniqueID(t, desiredClass, uniqueID);
  262.         
  263.     return result;
  264. }
  265.  
  266. //--------------------------------------------------------------------------------
  267. // TDBElementToken::BestType
  268. //--------------------------------------------------------------------------------
  269. DescType TDBElementToken::BestType(const TAETransaction& t, DescType propertyName)
  270. {
  271.     AConst<TDBProperty> propertyRecord = fRecord->GetPropertyRecord(TTransactionSuite::GetTransactionFromEvent(t), propertyName);
  272.     if(propertyRecord.Exists())
  273.     {
  274.         return propertyRecord->GetDataType(TTransactionSuite::GetTransactionFromEvent(t));
  275.     }
  276.     else
  277.         return typeBest;
  278. }
  279.  
  280. //--------------------------------------------------------------------------------
  281. // TDBElementToken::DefaultType
  282. //--------------------------------------------------------------------------------
  283. DescType TDBElementToken::DefaultType(const TAETransaction& t, DescType propertyName)
  284. {
  285.     AConst<TDBProperty> propertyRecord = fRecord->GetPropertyRecord(TTransactionSuite::GetTransactionFromEvent(t), propertyName);
  286.     if(propertyRecord.Exists())
  287.     {
  288.         return propertyRecord->GetDataType(TTransactionSuite::GetTransactionFromEvent(t));
  289.     }
  290.     else
  291.         return typeWildCard;
  292. }
  293.  
  294. //--------------------------------------------------------------------------------
  295. // TDBElementToken::CanReturnDataOfType
  296. //--------------------------------------------------------------------------------
  297. Boolean TDBElementToken::CanReturnDataOfType(const TAETransaction&, DescType /*propertyName*/, DescType /*desiredType*/)
  298. {
  299.     return true;
  300. }
  301.  
  302.  
  303. //--------------------------------------------------------------------------------
  304. // TDBElementToken::GetProperty
  305. //--------------------------------------------------------------------------------
  306. TDescriptor TDBElementToken::GetProperty(const TAETransaction& t, DescType propertyName, DescType desiredType, unsigned long additionalInfo /*= 0*/)
  307. {
  308.     TDescriptor result;
  309.     
  310.     switch(propertyName)
  311.     {
  312.         case pID:
  313.         {
  314.             result.SetSInt32Data(fRecord->RecordIndex());
  315.             break;
  316.         }
  317.         
  318.         case pIndex:
  319.         {
  320.             if(this->IsMetaRoot())
  321.                 FailErr(errAENoSuchObject);
  322.             else
  323.             {
  324.                 long index = 0;
  325.                 AConst<TDBRecord> treeTop = fRecord->TopOfTree(TTransactionSuite::GetTransactionFromEvent(t));
  326.                 for(TAbstractRecordIterator iter(TTransactionSuite::GetTransactionFromEvent(t), treeTop); iter.More(); iter.Next())
  327.                 {
  328.                     ++index;
  329.                     if(iter.Current()->RecordIndex() == fRecord->RecordIndex())
  330.                         break;
  331.                 }
  332.                 result.SetSInt32Data(index);
  333.             }
  334.             break;
  335.         }
  336.         
  337.         default:
  338.         {
  339.             AConst<TDBProperty> propertyRecord = fRecord->GetPropertyRecord(TTransactionSuite::GetTransactionFromEvent(t), propertyName);
  340.             if(propertyRecord.Exists())
  341.             {
  342.                 result = GetDataAsDescriptor(TTransactionSuite::GetTransactionFromEvent(t), propertyRecord);
  343.             }
  344.             else
  345.                 result = Inherited::GetProperty(t, propertyName, desiredType, additionalInfo);
  346.             
  347.             break;
  348.         }
  349.     }
  350.     
  351.     return result;
  352. }
  353.  
  354. //----------------------------------------------------------------------------------------
  355. // TDBElementToken::GetProperties:
  356. //----------------------------------------------------------------------------------------
  357. TDescriptor TDBElementToken::GetProperties(const TAETransaction& t, DescType desiredType)
  358. {
  359.     TDescriptor properties = Inherited::GetProperties(t, desiredType);
  360.     TDescriptor data;
  361.     OSErr err = noErr;
  362.     
  363.     AConst<TDBProperty> everyProperty = fRecord->Properties(TTransactionSuite::GetTransactionFromEvent(t));
  364.     for(TAbstractRecordIterator iter(TTransactionSuite::GetTransactionFromEvent(t), everyProperty->DBRecordCursor()); iter.More(); iter.Next())
  365.     {
  366.         AConst<TDBProperty> propertyRecord = iter.Current()->DBPropertyCursor();
  367.         DescType propertyName = propertyRecord->PropertyID(TTransactionSuite::GetTransactionFromEvent(t));
  368.         
  369.         //
  370.         // Skip properties already included by the call to Inherited
  371.         //
  372.         // There are better ways to do this; we could check to see if
  373.         // propertyName exists in the record 'everyProperty', or we
  374.         // could do a lookup in the property description table.  However,
  375.         // we already know what is in the property description table,
  376.         // so we just copy it here.  That's somewhat undesirable, but
  377.         // faster.
  378.         //
  379.         if(    (propertyName != pName) &&
  380.             (propertyName != pClass) &&
  381.             (propertyName != pDefaultType) &&
  382.             (propertyName != pBestType) &&
  383.             (propertyName != pID) &&
  384.             (propertyName != pIndex) )
  385.         {
  386.             Try
  387.             {
  388.                 //
  389.                 // Look up the data type to get; usually it will be the default type
  390.                 // or the best type for an individual property, but sometimes another
  391.                 // data type might be specified; in that case, only properties that
  392.                 // can return the specified type will be included in the result.
  393.                 //
  394.                 DescType typeToGet = desiredType;
  395.                 
  396.                 //
  397.                 // If the type to get is 'typeNull', then a description of the
  398.                 // property without any of its data is returned.
  399.                 //
  400.                 if(typeToGet != typeNull)
  401.                     {
  402.                     data = GetDataAsDescriptor(TTransactionSuite::GetTransactionFromEvent(t), propertyRecord);
  403.                     if((typeToGet != typeWildCard) && (typeToGet != typeBest))
  404.                         this->CoerceResultToRequestedType(data, typeToGet);
  405.                     }
  406.                 properties.PutDescriptorParameter(propertyName, data);
  407.                 }
  408.             Catch(err)
  409.                 {
  410.                 }
  411.         
  412.             data.Dispose();
  413.             }
  414.         }
  415.         
  416.     return properties;
  417.     } // TAbstractScriptableObject::GetProperties 
  418.  
  419. //--------------------------------------------------------------------------------
  420. // TDBElementToken::CompareProperty
  421. //--------------------------------------------------------------------------------
  422. Boolean TDBElementToken::CompareProperty(const TAETransaction& t, DescType propertyIdentifier, DescType comparisonOperator, TDescriptor compareWith)
  423. {
  424.     Boolean compareResult = false;
  425.     Boolean didCompare = false;
  426.     
  427.     AConst<TDBProperty> propertyRecord = fRecord->GetPropertyRecord(TTransactionSuite::GetTransactionFromEvent(t), propertyIdentifier);
  428.     if(propertyRecord.Exists())
  429.     {
  430.         short oldState = compareWith.Lock();
  431.  
  432.         switch(comparisonOperator)
  433.         {
  434.             case kAEEquals:        
  435.             case kASNotEqual:
  436.             case kAEGreaterThan:
  437.             case kAEGreaterThanEquals:
  438.             case kAELessThan:
  439.             case kASLessThanOrEqual:
  440.             {
  441.                 compareResult = InterpretCompareResult(comparisonOperator, propertyRecord->Compare(TTransactionSuite::GetTransactionFromEvent(t), compareWith), 0 );
  442.                 didCompare = true;
  443.                 break;
  444.             }
  445.             
  446.             case kAEContains:
  447.             {
  448.                 compareResult = propertyRecord->Contains(TTransactionSuite::GetTransactionFromEvent(t), compareWith);
  449.                 didCompare = true;
  450.                 break;
  451.             }
  452.             
  453.             //
  454.             // We don't export enough data to do begins with or
  455.             // ends with, so we'll just call Inherited and allow
  456.             // the comparison to be done the slow way.
  457.             //
  458.             case kAEBeginsWith:
  459.             case kAEEndsWith:
  460.             default:
  461.             {
  462.                 didCompare = false;
  463.                 break;
  464.             }
  465.         }
  466.  
  467.         compareWith.Unlock(oldState);
  468.     }
  469.     else
  470.         didCompare = false;
  471.  
  472.     //
  473.     // If we couldn't do the compare, then call Inherited
  474.     //
  475.     if(didCompare == false)
  476.         compareResult = Inherited::CompareProperty(t, propertyIdentifier, comparisonOperator, compareWith);
  477.     
  478.     return compareResult;
  479. } // TDBElementToken::CompareProperty
  480.  
  481. //--------------------------------------------------------------------------------
  482. // TDBElementToken::SetProperty
  483. //--------------------------------------------------------------------------------
  484. void TDBElementToken::SetProperty(const TAETransaction& t, DescType propertyName, TDescriptor& data, unsigned long /*additionalInfo = 0*/)
  485. {
  486.     switch(propertyName)
  487.     {
  488.         case pIndex:
  489.         case pID:
  490.         {
  491.             FailErr(errAENotModifiable);
  492.             break;
  493.         }
  494.         
  495.         default:
  496.         {
  497.             TTransaction* transaction = TTransactionSuite::GetTransactionFromEvent(t);
  498.             AnUpdate<TDBElement> updateElement = transaction->GetDBElementUpdatePointer(fRecord);
  499.         
  500. #if 0 // ◊ old way
  501.             HLock(data.DataHandle());
  502.             char* dataPtr = *data.DataHandle();
  503.             long dataLength = GetHandleSize(data.DataHandle());
  504.             long dataType = data.DescriptorType();
  505.             
  506.             updateElement->AddTypedProperty(transaction, propertyName, TConstDataReference(dataType, dataPtr, dataLength));
  507.             HUnlock(data.DataHandle());
  508. #endif
  509.             short oldState = data.Lock();
  510.             updateElement->AddTypedProperty(transaction, propertyName, data);
  511.             data.Unlock(oldState);
  512.             
  513.             //
  514.             // Make sure that the tree is still happy
  515.             //
  516.             fRecord->Verify(transaction, true);
  517.             break;
  518.         }
  519.     }
  520. }
  521.  
  522. //--------------------------------------------------------------------------------
  523. // TDBElementToken::BuildObjectSpecifier
  524. //--------------------------------------------------------------------------------
  525. TDescriptor TDBElementToken::BuildObjectSpecifier(const TAETransaction& t)
  526. {
  527.     //
  528.     // If this record is the metaroot, don't build
  529.     // an object specifier for it; just make one
  530.     // for the parent object
  531.     //
  532.     if(this->IsMetaRoot())
  533.         return this->BuildSpecifierForParent(t);
  534.     else
  535.         return Inherited::BuildObjectSpecifier(t);
  536. }
  537.  
  538. //--------------------------------------------------------------------------------
  539. // TDBElementToken::MakeKeyDataForSelf
  540. //--------------------------------------------------------------------------------
  541. void TDBElementToken::MakeKeyDataForSelf(const TAETransaction& t, DescType& keyForm, TDescriptor& keyData)
  542. {
  543.     //
  544.     // If we have a name property and this record is in a tree,
  545.     // then describe this element as "element xxx" of <parent specifier>
  546.     //
  547.     AConst<TDBProperty> nameProperty = fRecord->GetPropertyRecord(TTransactionSuite::GetTransactionFromEvent(t), pName);
  548.     if(nameProperty.Exists() && fRecord->RecordIsInATree(TTransactionSuite::GetTransactionFromEvent(t)))
  549.     {
  550.         Inherited::MakeKeyDataForSelf(t, keyForm, keyData);
  551.     }
  552.     //
  553.     // If there is no name property, OR if we have no parent, then describe
  554.     // this element by unique ID.
  555.     //
  556.     else
  557.     {
  558.         keyForm = formUniqueID;
  559.         keyData.SetSInt32Data(fRecord->RecordIndex());
  560.     }
  561. }
  562.  
  563. //--------------------------------------------------------------------------------
  564. // TDBElementToken::BuildSpecifierForParent
  565. //--------------------------------------------------------------------------------
  566. TDescriptor TDBElementToken::BuildSpecifierForParent(const TAETransaction& t)
  567. {
  568.     return Inherited::BuildSpecifierForParent(t);
  569. }
  570.  
  571. //--------------------------------------------------------------------------------
  572. // TDBElementToken::AECommand
  573. //--------------------------------------------------------------------------------
  574. TDescriptor TDBElementToken::AECommand(const TAETransaction& t, long aeCommandID, TAbstractScriptableObject* auxObjects, long auxInfo)
  575. {
  576.     TTransaction* transaction = TTransactionSuite::GetTransactionFromEvent(t);
  577.     TDescriptor result;
  578.     
  579.     switch(aeCommandID)
  580.     {
  581.         case kAEMove:
  582.         {
  583.             TAbstractObjectIterator* iter = auxObjects->DirectObjectIterator(t);
  584.             AnUpdate<TDBElement> destinationElement = transaction->GetDBElementUpdatePointer(fRecord);
  585.             
  586.             //
  587.             // There may be more than one item to move
  588.             //
  589.             for(iter->Reset(t); iter->More(t); iter->Next(t))
  590.             {
  591.                 TAbstractScriptableObject* current = iter->Current(t);
  592.                 
  593.                 //
  594.                 // We can only move DBElements
  595.                 //
  596.                 if(current->DerivedFrom(clDBElementToken))
  597.                 {
  598.                     AnUpdate<TDBElement> oneObjectToMove = transaction->GetDBElementUpdatePointer(((TDBElementToken*)current)->Record());
  599.  
  600.                     oneObjectToMove->RemoveFromTree(transaction);
  601.                     destinationElement->AddElement(transaction, oneObjectToMove);
  602.                     
  603.                     TDescriptor intermediate = current->BuildObjectSpecifier(t);
  604.                     result.AppendListAndDispose(intermediate);
  605.                 }
  606.                 
  607.                 current->DisposeDesignator();
  608.             }
  609.             
  610.             break;
  611.         }
  612.         
  613.         case kAEDelete:
  614.         {
  615.             result = this->BuildObjectSpecifier(t);
  616.             
  617.             AnUpdate<TDBElement> updateElement = transaction->GetDBElementUpdatePointer(fRecord);
  618.             updateElement->FreeThisRecord(transaction);
  619.             
  620.             break;
  621.         }
  622.         
  623.         default:
  624.         {
  625.             result = Inherited::AECommand(t, aeCommandID, auxObjects, auxInfo);
  626.             break;
  627.         }
  628.     }
  629.     
  630.     return result;
  631. }
  632.  
  633. //--------------------------------------------------------------------------------
  634. // TDBElementToken::CreateNewElement
  635. //--------------------------------------------------------------------------------
  636. TAbstractScriptableObject* TDBElementToken::CreateNewElement(const TAETransaction& t, DescType newObjectClass, TDescriptor /*initialData*/, TDescriptor /*initialProperties*/, Boolean& /*usedInitialData*/, Boolean& /*usedInitialProperties*/)
  637. {
  638.     TTransaction* transaction = TTransactionSuite::GetTransactionFromEvent(t);
  639.     AnUpdate<TDBElement> updateElement = transaction->GetDBElementUpdatePointer(fRecord);
  640.     
  641.     AnUpdate<TDBElement> newElement = fRecord->DBDocument()->NewDBElement(transaction);
  642.     newElement->AddTypedProperty(transaction, pClass, TConstDataReference(typeType, (Ptr)&newObjectClass, sizeof(DescType)));
  643.     updateElement->AddElement(transaction, newElement);
  644.  
  645.     //
  646.     // Make sure that the tree is still happy
  647.     //
  648.     fRecord->Verify(transaction, true);
  649.  
  650.     return new TDBElementToken(newElement);
  651. }
  652.  
  653. //----------------------------------------------------------------------------------------
  654. // TDBElementToken::ObjectsAreTheSame: 
  655. //----------------------------------------------------------------------------------------
  656. Boolean TDBElementToken::ObjectsAreTheSame(const TAETransaction&, TAbstractScriptableObject* objectToTest)
  657. {
  658.     Boolean areTheSame = false;
  659.     
  660.     if(objectToTest->DerivedFrom(clDBElementToken))
  661.     {
  662.         areTheSame = ((this->RecordIndex() == ((TDBElementToken*)objectToTest)->RecordIndex()) &&
  663.                 (this->DocumentIdentifier() == ((TDBElementToken*)objectToTest)->DocumentIdentifier()));
  664.     }
  665.         
  666.     return areTheSame;
  667. } // TDBElementToken::ObjectsAreTheSame
  668.  
  669. //--------------------------------------------------------------------------------
  670. // TDBElementToken::IsMetaRoot
  671. //--------------------------------------------------------------------------------
  672. Boolean TDBElementToken::IsMetaRoot()
  673. {
  674.     return fRecord->RecordIndex() == fRecord->DBDocument()->MetaRootIndex();
  675. } // TDBElementToken::IsMetaRoot
  676.  
  677. //--------------------------------------------------------------------------------
  678. // TDBElementToken::RecordIndex
  679. //--------------------------------------------------------------------------------
  680. long TDBElementToken::RecordIndex()
  681. {
  682.     return fRecord->RecordIndex();
  683. } // TDBElementToken::RecordIndex
  684.  
  685. //--------------------------------------------------------------------------------
  686. // TDBElementToken::DocumentIdentifier
  687. //--------------------------------------------------------------------------------
  688. Int64 TDBElementToken::DocumentIdentifier()
  689. {
  690.     return fRecord->DBDocument()->ObjectsKeySpace();
  691. } // TDBElementToken::DocumentIdentifier
  692.  
  693.